package twi.query.template2;

import java.awt.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;

import jtools.gui.DefaultLayoutNode;
import twi.OWLModel;
import twi.Utils;
import twi.query.template.NameFactory;
import twi.query.template2.view.AddIndividuumListener;
import twi.query.template2.view.ClassChooseListener;
import twi.query.template2.view.MaximizeListener;
import twi.query.template2.view.PropertyChangeListener;
import twi.query.template2.view.TemplatePropertyView;
import twi.query.template2.view.TemplateView;
import twi.query.template2.view.VariableChangeListener;
import twi_project.TWI;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;

public class TemplateClassNode extends DefaultLayoutNode implements TemplateNode, ClassChooseListener, VariableChangeListener, AddIndividuumListener, PropertyChangeListener, MaximizeListener{

	private static HashMap<String, String> variableNameList = new HashMap<String, String>();
	

	
	private String propertyName = null;
	private ArrayList<String> classNames = null;
	private TemplateNode parent = null;
	private transient OWLModel model = null;
	private HashMap<String, PropertyNode> propertyChildren = new HashMap<String, PropertyNode>();
	private ArrayList<TemplateNode> individualChildren = new ArrayList<TemplateNode>();
	
	private String currentClassName;
	private transient TemplateView templateView = null;
	private String variableName;
	private transient Template template = null;
	
	private boolean edit = true;



	private boolean showVariable;
	
	public TemplateClassNode(TemplateClassNode par,Template template, ArrayList<String> classNames, String propertyName){
		super(par);
		this.template = template;
		this.classNames = classNames;
		this.currentClassName = classNames.get(0);
		this.propertyName = propertyName;
		this.model = TWI.getInstance().getOntologieModel();
		setupPropertys();
	}
	
	private void setupPropertys() {
		OntClass oc = model.getOntClass(getOntClassName());
		List<OntProperty> list = Utils.getPropertyList(oc, true, true);
		for (int i = 0; i < list.size(); i++){
			boolean domain = Utils.isDomain(oc, list.get(i));
			String name = list.get(i).getLocalName();
			PropertyNode pn = new PropertyNode(name, null);
			pn.domain = domain;
			propertyChildren.put(name, pn);
		}
	}

	@Override
	public String getPropertyName() {
		return propertyName;
	}

	@Override
	public String getVariableName() {
		return this.variableName;
	}

	@Override
	public boolean isVisible() {
		return this.isVisible();
	}

	@Override
	public ArrayList<String> getAllPropertys() {
		ArrayList<String> out = new ArrayList<String>();
		Iterator<PropertyNode> iter = this.propertyChildren.values().iterator();
		while(iter.hasNext()){
			out.add(iter.next().propertyName);
		}
		return out;
	}

	@Override
	public ArrayList<TemplateNode> getChild(String propertyName) {
		return this.propertyChildren.get(propertyName).nodes;
		
	}

	@Override
	public TemplateNode getParent() {
		return this.parent;
	}

	@Override
	public ArrayList<String> getVisiblePropertys() {
		ArrayList<String> pn = new ArrayList<String>();
		Iterator<PropertyNode> iter = this.propertyChildren.values().iterator();
		while(iter.hasNext()){
			PropertyNode p = iter.next();
			if (p.visible)
				pn.add(p.propertyName);
		}
		return pn;
	}

	@Override
	public String getOntClassName() {
		return this.currentClassName;
	}
	private void deepRemoveAll() {
		this.propertyChildren.clear();
		this.deepRemove();
		this.setupPropertys();
		this.template.doLayout();
	}
	@Override
	public JComponent createView(boolean edit) {
		if (this.templateView != null)
			return this.templateView;
		
		this.templateView = new TemplateView(edit, this.classNames, this.currentClassName, this, this, this, this);
		this.templateView.addPropertyWindow(new TemplatePropertyView(edit, this.propertyChildren, this));
		return this.templateView;
	}
	
	
	
	
	
	

	@Override
	public void chooseClass(String className) {
		this.currentClassName = className;
		this.deepRemoveAll();
		this.setupPropertys();
		this.templateView.setHidePanel(new TemplatePropertyView(edit, this.propertyChildren, this));
		this.template.doLayout();
	}



	@Override
	public void changeProperty(boolean selected, String propertyName) {
		this.propertyChildren.get(propertyName).visible = selected;
		if (this.propertyChildren.get(propertyName).datatypeProperty)
			return ;
		if (selected){
			OntProperty prop =  Utils.getOntProperty(propertyName);
			if (prop == null)
				return ;
			OntResource or = null;
			if (this.propertyChildren.get(propertyName).domain)
				or = prop.getRange();
			else
				or = prop.getDomain();
			ArrayList<OntClass> classes = Utils.listClasses(or, true, false);
			ArrayList<String> s = new ArrayList<String>();
			for (int i = 0; i <classes.size(); i++){
				s.add(Utils.getLocalName(classes.get(i)));
			}
			TemplateClassNode tcn = new TemplateClassNode(this, this.template, s, propertyName);
			this.propertyChildren.get(propertyName).nodes.add(tcn);
			this.template.doLayout(tcn);
		}else{
			ArrayList<TemplateNode> li = this.propertyChildren.get(propertyName).nodes;
			for (int i = 0; i < li.size(); i++){
				li.get(i).deepRemove();
				this.removeChild(li.get(i));
			}
			li.clear();
//			this.propertyChildren.get(propertyName).node.deepRemove();
//			this.removeChild(this.propertyChildren.get(propertyName).node);
//			this.propertyChildren.get(propertyName).node = null;
			this.propertyChildren.get(propertyName).visible = false;
			this.template.doLayout(this);
		}
	}
	@Override
	public void addIndividum() {
		IndividualNode in = new IndividualNode(getOntClassName(), this, template);
		this.individualChildren.add(in);
		this.template.doLayout(in);
	}
	@Override
	public Component getComponent() {
		return createView(edit);
	}

	public void maximize() {
		if (this.templateView != null)
			this.templateView.setMaximized(true);
	}

	@Override
	public void rekursiveMinimize() {
		if (this.templateView != null)
			this.templateView.setMaximized(false);
		for (int i = 0; i < this.getChildCount(); i++){
			((TemplateNode)getChild(i)).rekursiveMinimize();
		}
	}

	@Override
	public void init(TemplateNode parent, boolean edit) {
		this.setParent(parent);
		this.edit = false;
		this.templateView = null;
		for (int i = 0; i < this.individualChildren.size(); i++)
			this.individualChildren.get(i).init(parent, edit);
		Iterator<PropertyNode> iter = this.propertyChildren.values().iterator();
		while(iter.hasNext()){
			PropertyNode p = iter.next();
			if (!p.nodes.isEmpty())
				for (int i = 0; i < p.nodes.size(); i++)
					p.nodes.get(i).init(this, edit);
		}
	}

	@Override
	public boolean isOptional() {
		return this.templateView.isOptional();
	}

	@Override
	public boolean showVariable() {
		if (!this.edit)
			return this.showVariable;
		else
			this.showVariable = this.templateView.showVariable();
		return this.showVariable;
//		return this.templateView.showVariable();
	}

	@Override
	public ArrayList<TemplateNode> getIndividualList() {
		return this.individualChildren;
	}

	@Override
	public String setVariableName(String n, boolean replace) {
		if (this.variableName != null && this.variableName.equals(n))
			return n;
		if (this.variableName != null && variableNameList.containsKey(n))
			if (replace){
				this.variableName = NameFactory.createNameFromClassName(n);
				return this.variableName;
			}else
				return n;
		if (variableNameList.containsKey(this.variableName))
			variableNameList.remove(variableName);
		variableName = n;
		variableNameList.put(n, n);
		return this.variableName;
	}

	@Override
	public void rekMaximize() {
		this.template.maximize(this);
	}

	@Override
	public PropertyNode getPropertyNode(String prop) {
		return this.propertyChildren.get(prop);
	}

	@Override
	public String getPropertyValue(String prop) {
		return this.templateView.getPropertyValue(prop);
	}

}
